Previous: Export in foreign buffers, Up: Exporting [Contents][Index]
Two hooks are run during the first steps of the export
process. The first one,
org-export-before-processing-hook is called before
expanding macros, Babel code and include keywords in the buffer.
The second one, org-export-before-parsing-hook, as
its name suggests, happens just before parsing the buffer. Their
main use is for heavy duties, that is duties involving structural
modifications of the document. For example, one may want to
remove every headline in the buffer during export. The following
code can achieve this:
(defun my-headline-removal (backend) "Remove all headlines in the current buffer. BACKEND is the export back-end being used, as a symbol." (org-map-entries (lambda () (delete-region (point) (progn (forward-line) (point)))))) (add-hook 'org-export-before-parsing-hook 'my-headline-removal)
Note that functions used in these hooks require a mandatory argument, a symbol representing the back-end used.
Filters are lists of functions applied on a specific part of the output from a given back-end. More explicitly, each time a back-end transforms an Org object or element into another language, all functions within a given filter type are called in turn on the string produced. The string returned by the last function will be the one used in the final output.
There are filters sets for each type of element or object, for
plain text, for the parse tree, for the export options and for
the final output. They are all named after the same scheme:
org-export-filter-TYPE-functions, where
TYPE is the type targeted by the filter. Valid types
are:
| bold | babel-call | center-block |
| clock | code | comment |
| comment-block | diary-sexp | drawer |
| dynamic-block | entity | example-block |
| export-block | export-snippet | final-output |
| fixed-width | footnote-definition | footnote-reference |
| headline | horizontal-rule | inline-babel-call |
| inline-src-block | inlinetask | italic |
| item | keyword | latex-environment |
| latex-fragment | line-break | link |
| node-property | options | paragraph |
| parse-tree | plain-list | plain-text |
| planning | property-drawer | quote-block |
| quote-section | radio-target | section |
| special-block | src-block | statistics-cookie |
| strike-through | subscript | superscript |
| table | table-cell | table-row |
| target | timestamp | underline |
| verbatim | verse-block |
For example, the following snippet allows me to use
non-breaking spaces in the Org buffer and get them translated
into LaTeX without using the \nbsp macro (where
_ stands for the non-breaking space):
(defun my-latex-filter-nobreaks (text backend info)
"Ensure \"_\" are properly handled in LaTeX export."
(when (org-export-derived-backend-p backend 'latex)
(replace-regexp-in-string "_" "~" text)))
(add-to-list 'org-export-filter-plain-text-functions
'my-latex-filter-nobreaks)
Three arguments must be provided to a filter: the code being
changed, the back-end used, and some information about the export
process. You can safely ignore the third argument for most
purposes. Note the use of
org-export-derived-backend-p, which ensures that the
filter will only be applied when using latex
back-end or any other back-end derived from it (e.g.,
beamer).
This is obviously the most powerful customization, since the changes happen at the parser level. Indeed, some export back-ends are built as extensions of other ones (e.g., Markdown back-end an extension of HTML back-end).
Extending a back-end means that if an element type is not transcoded by the new back-end, it will be handled by the original one. Hence you can extend specific parts of a back-end without too much work.
As an example, imagine we want the ascii back-end
to display the language used in a source block, when it is
available, but only when some attribute is non-nil,
like the following:
#+ATTR_ASCII: :language t
Because that back-end is lacking in that area, we are going to
create a new back-end, my-ascii that will do the
job.
(defun my-ascii-src-block (src-block contents info)
"Transcode a SRC-BLOCK element from Org to ASCII.
CONTENTS is nil. INFO is a plist used as a communication
channel."
(if (not (org-export-read-attribute :attr_ascii src-block :language))
(org-export-with-backend 'ascii src-block contents info)
(concat
(format ",--[ %s ]--\n%s`----"
(org-element-property :language src-block)
(replace-regexp-in-string
"^" "| "
(org-element-normalize-string
(org-export-format-code-default src-block info)))))))
(org-export-define-derived-backend 'my-ascii 'ascii
:translate-alist '((src-block . my-ascii-src-block)))
The my-ascii-src-block function looks at the
attribute above the element. If it isn’t true, it gives
hand to the ascii back-end. Otherwise, it creates a
box around the code, leaving room for the language. A new
back-end is then created. It only changes its behavior when
translating src-block type element. Now, all it
takes to use the new back-end is calling the following from an
Org buffer:
(org-export-to-buffer 'my-ascii "*Org MY-ASCII Export*")
It is obviously possible to write an interactive function for this, install it in the export dispatcher menu, and so on.
Previous: Export in foreign buffers, Up: Exporting [Contents][Index]